#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "blockqueue.hpp"
using namespace std;

#define CNUM 5
#define PNUM 2

//编写思路：先写main函数的轮廓，再写具体的类的内容
//注意理解：pthread_cond_wait接口和pthread_mutex_unlock接口
//其他理解：看起来逻辑对了，但打印结果有问题？ --> （1）显示器也是临界资源；（2）I/O请求时，线程也会被切换！

//阻塞队列作为参数由主线程传递可能较好，将来需要处理任务时直接将任务封装到阻塞队列即可！
//BlockQueue<int>* bq = new BlockQueue<int>(); 

string oper_vec = "+-*/%  ";
void* Consume(void* arg)
{
    BlockQueue<Task>* bq = static_cast<BlockQueue<Task>*>(arg);
    while(1)
    {
        //bq->pop();
        //int data = bq->pop();
        //cout << "consume: " << data << endl;
        //sleep(1);

        /*****************处理任务*********************/

        //1.从队列拿数据
        Task t = bq->pop();
        
        //2.模拟数据加工处理
        t();
        cout << "thread-" << pthread_self() % 100 << " consume a task ---" << t.GetTaskLog() << t.GetResultLog() << endl;
    }
}

void* Product(void* arg)
{
    BlockQueue<Task>* bq = static_cast<BlockQueue<Task>*>(arg);
    while(1)
    {
        //bq->push(data);
        //bq->push(t);
        //t._no++;
        //cout << "product: data-" << data++ <<endl;
        //usleep(500000);

        /*****************处理任务*********************/

        //1.模拟数据获取
        int data1 = rand() % 10 ;
        int data2 = rand() % 10 ;
        char oper = oper_vec[rand() % oper_vec.size()];
        Task t = Task(data1,data2,oper);

        //2.投放数据
        bq->push(t);
        cout <<"thread-" << pthread_self() % 100 << " product a task --- " << t.GetTaskLog() << endl;
        usleep(500000);
    }
}

//只将变量改成数组后 --> Segmentation falut! --> 没有防止误唤醒！(if改为while)导致队列满后仍生产者push
int main()
{
    srand((unsigned int)time(0));
    pthread_t consumer[CNUM], productor[PNUM];
    BlockQueue<Task>* bq = new BlockQueue<Task>(); 
    for(int i = 0; i < CNUM; i++)
    {
        pthread_create(&consumer[i],nullptr,Consume,bq);
    }
    for(int i = 0; i < PNUM; i++)
    {
        pthread_create(&productor[i],nullptr,Product,bq);
    }
    
    //pthread_create(&productor,nullptr,Product,&t);
    for(int i = 0; i < CNUM; i++)
    {
        pthread_join(consumer[i],nullptr);
    }
    for(int i = 0; i < PNUM; i++)
    {
       pthread_join(productor[i],nullptr); 
    }
    return 0;
}